package com.sdkx.wear_os.retrofit.download

import android.net.Uri
import android.webkit.MimeTypeMap
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import com.sdkx.wear_os.retrofit.response.RetrofitManager
import com.sdkx.wear_os.utils.ToastLogUtils.logUtil
import java.io.BufferedInputStream
import java.io.File
import java.io.FileOutputStream
import java.io.OutputStream

/**
 * 下载文件
 */
fun download(url: String, build: IDownloadBuild) = flow<DownloadStatus> {
    val response = RetrofitManager().downloadFile(url)
    response.body()?.let {
        val length = it.contentLength()
        val contentType = it.contentType().toString()
        val ios = it.byteStream()
        val info = try {
            downloadBuildToOutputStream(build, contentType)
        } catch (e: Exception) {
            emit(DownloadStatus.DownloadError(e))
            DownloadInfo(null)
            return@flow
        }
        val ops = info.ops
        if (ops == null) {
            emit(DownloadStatus.DownloadError(RuntimeException("下载出错")))
            return@flow
        }
        //下载长度
        var currentLength = 0
        //写入文件
        val bufferSize = 1028 * 8
        val buffer = ByteArray(bufferSize)
        val bufferedInputStream = BufferedInputStream(ios, bufferSize)
        var readLength: Int = 0
        try {
            while (bufferedInputStream.read(buffer, 0, bufferSize)
                    .also { readLength = it } != -1
            ) {
                ops.write(buffer, 0, readLength)
                currentLength += readLength
                emit(
                    DownloadStatus.DownloadProcess(
                        currentLength.toLong(),
                        length,
                        currentLength.toFloat() / length.toFloat()
                    )
                )
            }
            bufferedInputStream.close()
            ops.close()
            ios.close()
        } catch (e: Exception) {
            logUtil("download", e.message)
        }
        if (info.uri != null)
            emit(DownloadStatus.DownloadSuccess(info.uri))
        else emit(DownloadStatus.DownloadSuccess(Uri.fromFile(info.file)))

    } ?: kotlin.run {
        emit(DownloadStatus.DownloadError(RuntimeException("下载出错")))
    }
}.flowOn(Dispatchers.IO)

private fun downloadBuildToOutputStream(build: IDownloadBuild, contentType: String): DownloadInfo {
    val context = build.getContext()
    val uri = build.getUri(contentType)
    when {
        build.getDownloadFile() != null -> {
            val file = build.getDownloadFile()
            return DownloadInfo(FileOutputStream(file), file)
        }
        uri != null -> {
            return DownloadInfo(context.contentResolver.openOutputStream(uri), uri = uri)
        }
        else -> {
            val name = build.getFileName()
            val fileName = if (!name.isNullOrBlank()) name else "${System.currentTimeMillis()}.${
            MimeTypeMap.getSingleton().getExtensionFromMimeType(contentType)
            }"
            val file = File("${context.filesDir}", fileName)
            return DownloadInfo(FileOutputStream(file), file)
        }
    }


}

private class DownloadInfo(val ops: OutputStream?, val file: File? = null, val uri: Uri? = null)